summaryrefslogtreecommitdiffstats
path: root/src/core/hid/emulated_devices.h
blob: 76f9150df4b797fc91512c2a6a5db1f76fef3709 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <array>
#include <functional>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <vector>

#include "common/common_types.h"
#include "common/input.h"
#include "common/param_package.h"
#include "common/settings.h"
#include "core/hid/hid_types.h"

namespace Core::HID {
using KeyboardDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
                                   Settings::NativeKeyboard::NumKeyboardKeys>;
using KeyboardModifierDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
                                           Settings::NativeKeyboard::NumKeyboardMods>;
using MouseButtonDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
                                      Settings::NativeMouseButton::NumMouseButtons>;
using MouseAnalogDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
                                      Settings::NativeMouseWheel::NumMouseWheels>;
using MouseStickDevice = std::unique_ptr<Common::Input::InputDevice>;

using MouseButtonParams =
    std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons>;

using KeyboardValues =
    std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardKeys>;
using KeyboardModifierValues =
    std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>;
using MouseButtonValues =
    std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
using MouseAnalogValues =
    std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>;
using MouseStickValue = Common::Input::TouchStatus;

struct MousePosition {
    f32 x;
    f32 y;
};

struct DeviceStatus {
    // Data from input_common
    KeyboardValues keyboard_values{};
    KeyboardModifierValues keyboard_moddifier_values{};
    MouseButtonValues mouse_button_values{};
    MouseAnalogValues mouse_analog_values{};
    MouseStickValue mouse_stick_value{};

    // Data for HID serices
    KeyboardKey keyboard_state{};
    KeyboardModifier keyboard_moddifier_state{};
    MouseButton mouse_button_state{};
    MousePosition mouse_position_state{};
    AnalogStickState mouse_wheel_state{};
};

enum class DeviceTriggerType {
    Keyboard,
    KeyboardModdifier,
    Mouse,
    RingController,
};

struct InterfaceUpdateCallback {
    std::function<void(DeviceTriggerType)> on_change;
};

class EmulatedDevices {
public:
    /**
     * Contains all input data related to external devices that aren't necesarily a controller
     * This includes devices such as the keyboard or mouse
     */
    explicit EmulatedDevices();
    ~EmulatedDevices();

    YUZU_NON_COPYABLE(EmulatedDevices);
    YUZU_NON_MOVEABLE(EmulatedDevices);

    /// Removes all callbacks created from input devices
    void UnloadInput();

    /**
     * Sets the emulated devices into configuring mode
     * This prevents the modification of the HID state of the emulated devices by input commands
     */
    void EnableConfiguration();

    /// Returns the emulated devices into normal mode, allowing the modification of the HID state
    void DisableConfiguration();

    /// Returns true if the emulated device is in configuring mode
    bool IsConfiguring() const;

    /// Reload all input devices
    void ReloadInput();

    /// Overrides current mapped devices with the stored configuration and reloads all input devices
    void ReloadFromSettings();

    /// Saves the current mapped configuration
    void SaveCurrentConfig();

    /// Reverts any mapped changes made that weren't saved
    void RestoreConfig();

    // Returns the current mapped ring device
    Common::ParamPackage GetRingParam() const;

    /**
     * Updates the current mapped ring device
     * @param param ParamPackage with ring sensor data to be mapped
     */
    void SetRingParam(Common::ParamPackage param);

    /// Returns the latest status of button input from the keyboard with parameters
    KeyboardValues GetKeyboardValues() const;

    /// Returns the latest status of button input from the keyboard modifiers with parameters
    KeyboardModifierValues GetKeyboardModdifierValues() const;

    /// Returns the latest status of button input from the mouse with parameters
    MouseButtonValues GetMouseButtonsValues() const;

    /// Returns the latest status of button input from the keyboard
    KeyboardKey GetKeyboard() const;

    /// Returns the latest status of button input from the keyboard modifiers
    KeyboardModifier GetKeyboardModifier() const;

    /// Returns the latest status of button input from the mouse
    MouseButton GetMouseButtons() const;

    /// Returns the latest mouse coordinates
    MousePosition GetMousePosition() const;

    /// Returns the latest mouse wheel change
    AnalogStickState GetMouseWheel() const;

    /**
     * Adds a callback to the list of events
     * @param update_callback InterfaceUpdateCallback that will be triggered
     * @return an unique key corresponding to the callback index in the list
     */
    int SetCallback(InterfaceUpdateCallback update_callback);

    /**
     * Removes a callback from the list stopping any future events to this object
     * @param key Key corresponding to the callback index in the list
     */
    void DeleteCallback(int key);

private:
    /// Helps assigning a value to keyboard_state
    void UpdateKey(std::size_t key_index, bool status);

    /**
     * Updates the touch status of the keyboard device
     * @param callback A CallbackStatus containing the key status
     * @param index key ID to be updated
     */
    void SetKeyboardButton(const Common::Input::CallbackStatus& callback, std::size_t index);

    /**
     * Updates the keyboard status of the keyboard device
     * @param callback A CallbackStatus containing the modifier key status
     * @param index modifier key ID to be updated
     */
    void SetKeyboardModifier(const Common::Input::CallbackStatus& callback, std::size_t index);

    /**
     * Updates the mouse button status of the mouse device
     * @param callback A CallbackStatus containing the button status
     * @param index Button ID to be updated
     */
    void SetMouseButton(const Common::Input::CallbackStatus& callback, std::size_t index);

    /**
     * Updates the mouse wheel status of the mouse device
     * @param callback A CallbackStatus containing the wheel status
     * @param index wheel ID to be updated
     */
    void SetMouseAnalog(const Common::Input::CallbackStatus& callback, std::size_t index);

    /**
     * Updates the mouse position status of the mouse device
     * @param callback A CallbackStatus containing the position status
     */
    void SetMouseStick(const Common::Input::CallbackStatus& callback);

    /**
     * Updates the ring analog sensor status of the ring controller
     * @param callback A CallbackStatus containing the force status
     */
    void SetRingAnalog(const Common::Input::CallbackStatus& callback);

    /**
     * Triggers a callback that something has changed on the device status
     * @param type Input type of the event to trigger
     */
    void TriggerOnChange(DeviceTriggerType type);

    bool is_configuring{false};

    KeyboardDevices keyboard_devices;
    KeyboardModifierDevices keyboard_modifier_devices;
    MouseButtonDevices mouse_button_devices;
    MouseAnalogDevices mouse_analog_devices;
    MouseStickDevice mouse_stick_device;

    mutable std::mutex mutex;
    mutable std::mutex callback_mutex;
    std::unordered_map<int, InterfaceUpdateCallback> callback_list;
    int last_callback_key = 0;

    // Stores the current status of all external device input
    DeviceStatus device_status;
};

} // namespace Core::HID